/*
 *  Copyright 2015-2016, RenGu Technology (BeiJing) Co., Ltd.
 *  All right reserved.
 *
 *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  THE CONTENTS OF THIS FILE MAY NOT BE DISCLOSED TO THIR PARTIES,
 *  COPIED OR DUPLICATED IN ANY FORM, IN WHOLE OR IN PART,
 *  WITHOUT THE PRIOR WRITTEN PERMISSION OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  AcctDetailMapperImpl
 *
 *  Edit History:
 *      lizhangtao Created on 2020年04月12日
 *
 */
package cc.rengu.igas.acct.common.dao.impl;

import cc.rengu.igas.acct.common.constant.AcctCommonConstant;
import cc.rengu.igas.acct.common.constant.AcctSqlMapperId;
import cc.rengu.igas.acct.common.dao.AcctDetailMapper;
import cc.rengu.igas.acct.common.dao.MapperCommon;
import cc.rengu.igas.acct.common.entity.AcctDetail;
import cc.rengu.igas.acct.common.enums.AcctRespCodeEnum;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.bean.PageInfo;
import cc.rengu.oltp.utility.bean.PageResult;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.DbsUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.cache.UnifiedCache;
import cc.rengu.utility.dbs.Database;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 账户记账明细表操作实现类
 *
 * @author lizhangtao
 * @version 1.0
 * @date 2020/5/8
 */
public class AcctDetailMapperImpl extends MapperCommon implements AcctDetailMapper {
    /**
     * 登记记账明细
     * 成功直接提交，失败回滚
     *
     * @param acctDetail 账户记账明细
     * @return Database.DBS_SUCCESS成功，
     * Database.DBS_PKEY_DUPLICATE主键重复，
     * 违反唯一约束需要自己判断，其他失败
     * 为区别普通的数据库返回的应答码及异常，异常时返回Integer.MIN_VALUE
     */
    @Override
    public int insert2AcctDetail(AcctDetail acctDetail, DbsUtil dbsUtil) {
        try {
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.INSERT2ACCT_DETAIL);
            return dbsUtil.dbsExecuteTransactionSql(sqlStr, acctDetail, null);
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            return Integer.MIN_VALUE;
        }
    }

    /**
     * 以记账流水查询原记账明细
     *
     * @param instId     法人机构号
     * @param acctSeqNum 记账流水号
     * @return 成功返回记账明细，未查询到数据返回null
     * @throws BizException 其他失败及异常抛出异常
     */
    @Override
    public AcctDetail selectAcctDetailByAcctSeqNum(String instId, String acctSeqNum) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetail = new AcctDetail();
            acctDetail.setInstId(instId);
            acctDetail.setAcctSeqNum(acctSeqNum);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.SELECT_ACCT_DETAIL_BY_ACCT_SEQ_NUM);
            int retCode = dbsUtil.dbsExecuteSql(sqlStr, acctDetail, acctDetail);
            if (Database.DBS_SUCCESS == retCode) {
                return acctDetail;
            } else if (Database.DBS_NOT_FOUND == retCode) {
                return null;
            } else {
                rglog.error("查询失败(非未查询到数据)");
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 以交易上送的外部流水查询原记账明细
     *
     * @param instId      法人机构号
     * @param transSeqNum 记账流水号
     * @return 成功返回记账明细，未查询到数据返回null
     * @throws BizException 其他失败及异常抛出异常
     */
    @Override
    public AcctDetail selectAcctDetailByTransSeqNum(String instId, String transSeqNum) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetail = new AcctDetail();
            acctDetail.setInstId(instId);
            acctDetail.setFrontSeqNum(transSeqNum);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.SELECT_ACCT_DETAIL_BY_FRONT_SEQ_NUM);
            int retCode = dbsUtil.dbsExecuteSql(sqlStr, acctDetail, acctDetail);
            if (Database.DBS_SUCCESS == retCode) {
                return acctDetail;
            } else if (Database.DBS_NOT_FOUND == retCode) {
                return null;
            } else {
                rglog.error("查询失败(非未查询到数据)");
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 更新明细为已经撤销
     *
     * @param instId         法人机构号
     * @param origAcctSeqNum 原记账流水号
     * @throws BizException 无数据、失败、异常
     */
    @Override
    public void updOrigCanceledByAcctSeqNum(String instId, String origAcctSeqNum, String fronSeqNum, String acctSeqNum, DbsUtil dbsUtil) throws BizException {
        try {
            AcctDetail acctDetail = new AcctDetail();
            acctDetail.setInstId(instId);
            acctDetail.setAcctSeqNum(origAcctSeqNum);
            acctDetail.setOrigFrontSeqNum(fronSeqNum);
            acctDetail.setOrigAcctSeqNum(acctSeqNum);
            acctDetail.setUpdateTime(DateUtil.getCurrentDateTime(AcctCommonConstant.DATETIME_FORMAT_MS));
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.UPD_ACCT_DETAIL_CANCELED);
            int iRetCode = dbsUtil.dbsExecuteTransactionSql(sqlStr, acctDetail, null);
            if (Database.DBS_SUCCESS != iRetCode) {
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 更新明细为已经完成
     *
     * @param instId         法人机构号
     * @param origAcctSeqNum 原记账流水号
     * @throws BizException 无数据、失败、异常
     */
    @Override
    public void updOrigCompletedByAcctSeqNum(String instId, String origAcctSeqNum, String fronSeqNum, String acctSeqNum, DbsUtil dbsUtil) throws BizException {
        try {
            AcctDetail acctDetail = new AcctDetail();
            acctDetail.setInstId(instId);
            acctDetail.setAcctSeqNum(origAcctSeqNum);
            acctDetail.setOrigAcctSeqNum(acctSeqNum);
            acctDetail.setOrigFrontSeqNum(fronSeqNum);
            acctDetail.setUpdateTime(DateUtil.getCurrentDateTime(AcctCommonConstant.DATETIME_FORMAT_MS));
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.UPD_ACCT_DETAIL_COMPLETED);
            int iRetCode = dbsUtil.dbsExecuteTransactionSql(sqlStr, acctDetail, null);
            if (Database.DBS_SUCCESS != iRetCode) {
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 指定账号查询日期时间段内按照交易时间正序排列的某指定区间的所有交易
     *
     * @param instId     法人机构号
     * @param acctNo     账号
     * @param startDate  开始日期（包括）
     * @param endDate    截止日期（包括）
     * @param numPerPage 每页记录数
     * @param pageNo     查询指定某页
     * @return 记账明细实体list，无数据返回null
     * @throws BizException 其他失败或者异常抛出异常
     */
    @Override
    public PageResult fetchPageListByAcctNoAndStartEndDate(String instId, String acctNo, String startDate, String endDate,
                                                           int numPerPage, int pageNo) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetailIn = new AcctDetail();
            acctDetailIn.setInstId(instId);
            acctDetailIn.setAcctNo(acctNo);
            acctDetailIn.setTxnDate(startDate);
            //借用remark2作为截止日期
            acctDetailIn.setRemark2(endDate);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE,
                    AcctSqlMapperId.FETCH_LIST_BY_TXN_DATE_AND_ACCT_NO_AND_PAGE);
            PageInfo pageInfo = new PageInfo();
            pageInfo.setPageSize(numPerPage);
            pageInfo.setPageIndex(pageNo);
            return dbsUtil.dbsFetchPageListData(sqlStr, acctDetailIn, AcctDetail.class, pageInfo);
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 指定客户号查询日期时间段内按照交易时间正序排列的某指定区间的所有交易
     *
     * @param instId     法人机构号
     * @param customerId 客户号
     * @param startDate  开始日期（包括）
     * @param endDate    截止日期（包括）
     * @param numPerPage 每页记录数
     * @param pageNo     查询指定某页
     * @return 记账明细实体list及页数信息，无数据返回null
     * @throws BizException 其他失败或者异常抛出异常
     */
    @Override
    public PageResult fetchPageListByCustomerIdAndStartEndDate(String instId, String customerId,
                                                               String startDate, String endDate,
                                                               int numPerPage, int pageNo) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetailIn = new AcctDetail();
            acctDetailIn.setInstId(instId);
            acctDetailIn.setCustomerId(customerId);
            acctDetailIn.setTxnDate(startDate);
            //借用remark2作为截止日期
            acctDetailIn.setRemark2(endDate);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE,
                    AcctSqlMapperId.FETCH_LIST_BY_TXN_DATE_AND_CUSTOMER_ID_AND_PAGE);
            PageInfo pageInfo = new PageInfo();
            pageInfo.setPageSize(numPerPage);
            pageInfo.setPageIndex(pageNo);
            return dbsUtil.dbsFetchPageListData(sqlStr, acctDetailIn, AcctDetail.class, pageInfo);
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 指定外部用户查询日期时间段内按照交易时间正序排列的某指定区间的所有交易
     *
     * @param instId     法人机构号
     * @param userType   外部用户类型
     * @param userId     外部用户id
     * @param startDate  开始日期（包括）
     * @param endDate    截止日期（包括）
     * @param numPerPage 每页记录数
     * @param pageNo     查询指定某页
     * @return 记账明细实体list及页数信息，无数据返回null
     * @throws BizException 其他失败或者异常抛出异常
     */
    @Override
    public PageResult fetchPageListByUserAndStartEndDate(String instId, String userType, String userId,
                                                         String startDate, String endDate,
                                                         int numPerPage, int pageNo) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetailIn = new AcctDetail();
            acctDetailIn.setInstId(instId);
            acctDetailIn.setUserType(userType);
            acctDetailIn.setUserId(userId);
            acctDetailIn.setTxnDate(startDate);
            //借用remark2作为截止日期
            acctDetailIn.setRemark2(endDate);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE,
                    AcctSqlMapperId.FETCH_LIST_BY_TXN_DATE_AND_USER_AND_PAGE);
            PageInfo pageInfo = new PageInfo();
            pageInfo.setPageSize(numPerPage);
            pageInfo.setPageIndex(pageNo);
            return dbsUtil.dbsFetchPageListData(sqlStr, acctDetailIn, AcctDetail.class, pageInfo);
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 指定外部调用方原请求流水号查询所有
     *
     * @param instId      法人机构号
     * @param frontSeqNum 外部调用方流水号
     * @return List<AcctDetail> 记账明细实体list及，无数据返回null
     * @throws BizException 其他失败或者异常抛出异常
     */
    @Override
    public List<AcctDetail> fetchListByFrontSeqNum(String instId, String frontSeqNum) throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetailIn = new AcctDetail();
            acctDetailIn.setInstId(instId);
            acctDetailIn.setFrontSeqNum(frontSeqNum);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE,
                    AcctSqlMapperId.FETCH_LIST_BY_FRONT_SEQ_NUM);
            return dbsUtil.dbsFetchLimitListData(sqlStr, acctDetailIn, AcctDetail.class).stream().map(item -> (AcctDetail) (item)).collect(Collectors.toList());
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    @Override
    public AcctDetail selectAcctDetailByFromSeqNumCustomerIdAndUserId(String userId, String userType, String acctNo, String customerId, String traceNo, String instId) {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetail = new AcctDetail();
            acctDetail.setInstId(instId);
            acctDetail.setFrontSeqNum(traceNo);
            acctDetail.setUserId(userId);
            acctDetail.setUserType(userType);
            acctDetail.setAcctNo(acctNo);
            acctDetail.setCustomerId(customerId);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.SELECT_ACCT_DETAIL_BY_FRONT_SEQ_NUM_CUSTOMER_ID_AND_USER_ID);
            int retCode = dbsUtil.dbsExecuteSql(sqlStr, acctDetail, acctDetail);
            if (Database.DBS_SUCCESS == retCode) {
                return acctDetail;
            } else if (Database.DBS_NOT_FOUND == retCode) {
                return null;
            } else {
                rglog.error("查询失败(非未查询到数据,可能结果多条)");
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    @Override
    public List<AcctDetail> fetchListByOrigAcctSeqNum(String instId, String freezeAcctSeqNum, String acctNo, String customerId, String userType, String userId) {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            AcctDetail acctDetailIn = new AcctDetail();
            acctDetailIn.setInstId(instId);
            acctDetailIn.setOrigAcctSeqNum(freezeAcctSeqNum);
            acctDetailIn.setUserId(userId);
            acctDetailIn.setUserType(userType);
            acctDetailIn.setAcctNo(acctNo);
            acctDetailIn.setCustomerId(customerId);
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE,
                    AcctSqlMapperId.FETCH_LIST_BY_ORIG_ACCT_SEQ_NUM);
            return dbsUtil.dbsFetchLimitListData(sqlStr, acctDetailIn, AcctDetail.class).stream().map(item -> (AcctDetail) (item)).collect(Collectors.toList());
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }
}
